#include "app_serial.h"

#include <unistd.h>
#include "thirdparty/log/log.h"

static int app_serial_setRawMode(SerialDevice *serial_device)
{
    // 获取串口的属性
    struct termios attr;
    if (tcgetattr(serial_device->super.fd, &attr) < 0)
    {
        log_warn("tcgetattr error");
        return -1;
    }

    // 更改属性
    cfmakeraw(&attr);

    // 将属性写回串口
    return tcsetattr(serial_device->super.fd, TCSAFLUSH, &attr);
}

int app_serial_init(SerialDevice *serial_device, char *filename)
{
    if (app_device_init(&serial_device->super, filename) < 0)
    {
        log_warn("app_device_init error");
        return -1;
    }
    if (app_serial_setBaudRate(serial_device, BaudRate_9600) < 0)
    {
        log_warn("app_serial_setBaudRate error");
        return -1;
    }
    if (app_serial_setParity(serial_device, Parity_None) < 0)
    {
        log_warn("app_serial_setParity error");
        return -1;
    }
    if (app_serial_setDataBits(serial_device, DataBits_8) < 0)
    {
        log_warn("app_serial_setDataBits error");
        return -1;
    }
    if (app_serial_setStopBits(serial_device, StopBits_1) < 0)
    {
        log_warn("app_serial_setStopBits error");
        return -1;
    }
    if (app_serial_setRawMode(serial_device) < 0)
    {
        log_warn("app_serial_setRawMode error");
        return -1;
    }
    if (app_serial_setBlockMode(serial_device, 1) < 0)
    {
        log_warn("app_serial_setBlockMode error");
        return -1;
    }

    return app_serial_flush(serial_device);
}

int app_serial_setBaudRate(SerialDevice *device, BaudRate baud_rate)
{

    // 获取串口的属性
    struct termios attr;
    if (tcgetattr(device->super.fd, &attr) < 0)
    {
        log_warn("tcgetattr error");
        return -1;
    }

    // 更改波特率
    cfsetispeed(&attr, baud_rate);
    cfsetospeed(&attr, baud_rate);

    // 将属性写回串口
    return tcsetattr(device->super.fd, TCSAFLUSH, &attr);
}

int app_serial_setParity(SerialDevice *device, Parity parity)
{
    // 获取串口的属性
    struct termios attr;
    if (tcgetattr(device->super.fd, &attr) < 0)
    {
        log_warn("tcgetattr error");
        return -1;
    }

    // 更改波特率
    attr.c_cflag &= ~(PARENB | PARODD);
    attr.c_cflag |= parity;

    // 将属性写回串口
    return tcsetattr(device->super.fd, TCSAFLUSH, &attr);
}

int app_serial_setDataBits(SerialDevice *device, DataBits data_bits)
{
    // 获取串口的属性
    struct termios attr;
    if (tcgetattr(device->super.fd, &attr) < 0)
    {
        log_warn("tcgetattr error");
        return -1;
    }

    // 更改波特率
    attr.c_cflag &= ~CSIZE;
    attr.c_cflag |= data_bits;

    // 将属性写回串口
    return tcsetattr(device->super.fd, TCSAFLUSH, &attr);
}

int app_serial_setStopBits(SerialDevice *device, StopBits stop_bits)
{
    // 获取串口的属性
    struct termios attr;
    if (tcgetattr(device->super.fd, &attr) < 0)
    {
        log_warn("tcgetattr error");
        return -1;
    }

    // 更改波特率
    attr.c_cflag &= ~CSTOPB;
    attr.c_cflag |= stop_bits;

    // 将属性写回串口
    return tcsetattr(device->super.fd, TCSAFLUSH, &attr);
}

int app_serial_setBlockMode(SerialDevice *device, int enable)
{
    // 获取串口的属性
    struct termios attr;
    if (tcgetattr(device->super.fd, &attr) < 0)
    {
        log_warn("tcgetattr error");
        return -1;
    }

    // 设置串口阻塞模式
    if (enable)
    {
        // 读取至少一个字节
        attr.c_cc[VMIN] = 1;
        attr.c_cc[VTIME] = 0;
    }
    else
    {
        // 读取 无数据200ms超时
        attr.c_cc[VMIN] = 0;
        attr.c_cc[VTIME] = 2;
    }

    // 将属性写回串口
    return tcsetattr(device->super.fd, TCSAFLUSH, &attr);
}

int app_serial_flush(SerialDevice *device)
{
    return tcflush(device->super.fd, TCIOFLUSH);
}
